#include "gtree.h"
#include "syntax.tab.hpp"
#include <cstdlib>
#include <string>
#include <cstring>
#include <iostream>
#include <cstdarg>
#include <cctype>
using namespace std;
extern char *yytext;
extern int yylineno;
GTNode *newNode(int token, string name, int num, ...)
{
    GTNode *r = (GTNode *)malloc(sizeof(GTNode));
    if (!r)
        exit(-1);
    memset(r, 0, sizeof(GTNode));
    va_list args;
    va_start(args, num);
    r->token = token;
    r->name = name;
    if (token == INT)
    {
        r->name="INT";
        if (yytext[0] == '0')
            if (tolower(yytext[1]) == 'x')
            {
                int sum = 0;
                for (int i = 2; i < strlen(yytext); i++)
                {
                    if (tolower(yytext[i]) > 'f')
                    {
                        cout << "Error A @line " << yylineno << " invalid number\n";
                        exit(-1);
                    }
                    if (tolower(yytext[i]) >= '0' && tolower(yytext[i]) <= '9')
                        sum = sum * 16 + yytext[i] - '0';
                    else if (tolower(yytext[i]) >= 'a' && tolower(yytext[i]) <= 'f')
                        sum = sum * 16 + tolower(yytext[i]) - 'a' + 10;
                }
                r->ivalue = sum;
            }
            else
            {
                int sum = 0;
                for (int i = 0; i < strlen(yytext); i++)
                {
                    if (yytext[i] > '7')
                    {
                        cout << "Error A @line " << yylineno << " invalid number\n";
                        exit(-1);
                    }
                    sum = sum * 8 + yytext[i] - '0';
                }
                r->ivalue = sum;
            }

        else
            r->ivalue = atoi(yytext);
    }
    else if (token == FLOAT)
    {
        r->name="FLOAT";
        r->fvalue = atof(yytext);
    }
    else if (token == ID)
    {
        strcpy(r->id, yytext);
    }
    r->lineno = yylineno;
    if (num-- > 0)
    {
        r->child = va_arg(args, GTNode *);
        r->lineno = r->child->lineno;
        GTNode *tmp = r->child;
        while (num-- > 0)
        {
            tmp->sibiling = va_arg(args, GTNode *);
            tmp = tmp->sibiling;
        }
    }
    return r;
}
void travel(GTNode *head, int indent)
{
    if (head)
    {
        if (head->token == -1)
            cout << endl;
        for (int i = 0; i < indent && head->token != -1; ++i)
        {
            cout << " ";
        }
        switch (head->token)
        {
        case -1:
            break;
        case ID:
            cout << "ID: " << head->id << endl;
            break;
        case INT:
            cout << "INT: " << head->ivalue << endl;
            break;
        case FLOAT:
            cout << "FLOAT: " << head->fvalue << endl;
            break;
        case LP:
            cout << "LP" << endl;
            break;
        case RP:
            cout << "RP" << endl;
            break;
        case LC:
            cout << "LC" << endl;
            break;
        case RC:
            cout << "RC" << endl;
            break;
        case SEMI:
            cout << "SEMI" << endl;
            break;
        case TYPE:
            cout << "TYPE: " << head->name << endl;
            break;
        case ASSIGNOP:
            cout << "ASSIGNOP" << endl;
            break;
        case PLUS:
            cout << "PLUS" << endl;
            break;
        case MINUS:
            cout << "MINUS" << endl;
            break;
        case COMMA:
            cout << "COMMA" << endl;
            break;
        default:
            cout << head->name << "(" << head->lineno << ")" << endl;
            break;
        }
        travel(head->child, indent + 3);
        travel(head->sibiling, indent);
    }
}
